home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
ip
/
ka9q
/
src890906.arc
/
TIMER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-09-07
|
4KB
|
185 lines
#include <stdio.h>
#include "global.h"
#include "timer.h"
#include "proc.h"
#ifdef MSDOS
#include "pc.h"
#endif
#ifdef AMIGA
#include "amiga.h"
#endif
static struct timer *Timers; /* Head of running timer chain */
int32 Clock;
void
timerproc(i,v1,v2)
int i;
void *v1,*v2;
{
register struct timer *t;
register struct timer *expired = NULLTIMER;
char i_state;
for(;;){
i_state = dirps(); /* Tick is modified by an interrupt */
while(Tick == 0)
pwait(&Tick);
Tick--;
restore(i_state);
Clock++;
systick(); /* Machine-dependent per-tick stuff */
/* Decrement the first timer. If it expires,
* take it off the running list and put it
* on a singly linked list of expired timers
*/
if(Timers != NULLTIMER)
Timers->count--;
else
continue; /* Nothing else on this tick */
while(Timers != NULLTIMER && Timers->count <= 0){
if(Timers->next == Timers){
printf("PANIC: Timer loop at %lx\n",
(long)Timers);
iostop();
exit(1);
}
/* Save Timers since stop_timer will change it */
t = Timers;
stop_timer(t);
t->state = TIMER_EXPIRE;
/* Add to expired timer list */
t->next = expired;
expired = t;
}
/* Now go through the list of expired timers, removing each
* one and kicking the notify function, if there is one
*/
while((t = expired) != NULLTIMER){
expired = t->next;
if(t->func){
(*t->func)(t->arg);
}
}
}
}
/* Start a timer */
void
start_timer(t)
struct timer *t;
{
register struct timer *tnext,*tprev;
int32 tot;
if(t == NULLTIMER)
return;
if(t->state == TIMER_RUN)
stop_timer(t);
if(t->start == 0)
return; /* A start value of 0 disables the timer */
t->state = TIMER_RUN;
/* Find right place on list for this guy */
tot = 0;
tprev = NULLTIMER;
for(tnext = Timers;tnext != NULLTIMER;tnext = tprev->next){
if(tnext->count + tot > t->start)
break;
tprev = tnext;
tot += tnext->count;
}
/* At this point, tprev points to the entry that should go right
* before us, and tnext points to the entry just after us. Either or
* both may be null.
*/
t->count = t->start - tot; /* Adjust for entries before us */
if((t->prev = tprev) == NULLTIMER)
Timers = t; /* Put at beginning */
else
tprev->next = t;
if((t->next = tnext) != NULLTIMER){
tnext->prev = t;
/* Adjust the following entry's count */
tnext->count -= t->count;
}
}
/* Stop a timer */
void
stop_timer(t)
register struct timer *t;
{
register struct timer *tp;
if(t == NULLTIMER)
return;
if(t->state == TIMER_RUN){
/* Delete from active timer list */
if(t->next != NULLTIMER)
t->next->prev = t->prev;
if(t->prev != NULLTIMER)
t->prev->next = t->next;
else
Timers = t->next;
/* Adjust count for the next timer */
if((tp = t->next) != NULLTIMER)
tp->count += t->count;
}
t->state = TIMER_STOP;
}
/* Return count of ticks remaining on this timer */
int32
read_timer(t)
struct timer *t;
{
register struct timer *tp;
int32 tot;
if(t->state != TIMER_RUN)
return 0;
tot = 0;
for(tp = Timers;tp != NULLTIMER; tp = tp->next){
tot += tp->count;
if(tp == t)
break;
}
return tot;
}
/* Delay process for specified number of ticks */
void
pause(ticks)
int32 ticks;
{
if(Curproc == NULLPROC || ticks == 0)
return;
alarm(ticks);
/* The actual event doesn't matter, since we'll be alerted */
while(Curproc->alarm.state == TIMER_RUN && pwait(Curproc) == 1)
;
alarm(0L); /* Make sure it's stopped, in case we were killed */
}
static void
t_alarm(x)
void *x;
{
alert((struct proc *)x,1);
}
/* Send signal to current process after specified number of ticks */
void
alarm(ticks)
int32 ticks;
{
if(Curproc != NULLPROC){
Curproc->alarm.start = ticks;
Curproc->alarm.func = t_alarm;
Curproc->alarm.arg = (char *)Curproc;
start_timer(&Curproc->alarm);
}
}